package com.ltmonitor.thread;

import org.apache.log4j.Logger;

import com.alibaba.druid.stat.TableStat.Name;
import com.google.common.util.concurrent.Service;
import com.sun.tools.javah.resources.l10n;

/**
 * <p>基础服务线程</p>
 * <p>继承于Thread，用于封装基本的数据对象和基本方法</p>
 * 说明：
 * 		继承本类的子类:
 * 			单次循环时间可以指定，sleepNum ，单位毫秒，不建议超过5000，
 * 			如果单次功能循环时间超过5000毫秒，那么可以在 threadServcieInit 方法中重新设置sleepCount的值，
 * 							循环时间为：sleepNum * sleepCount
 * 			初始化方法，重写 protected String  threadServcieInit(){}方法即可
 * 			循环执行方法，重写 protected void threadServiceRun(){}方法即可
 * @author shinion
 * @time 2019-08-08
 *
 */
public class BasicServiceThread extends Thread {
	
	//记录线程相关信息的日志，最低输出级别：info
	protected Logger threadLog = Logger.getLogger("thread"); 
	

	/**
	 * 线程标记，true表示允许运行，false表示不允许运行
	 */
	private boolean threadFlg = true; 
	
	
	/**
	 *状态标记，由线程管理器查验，发现为true，则置为false，如果发现为false，则 stateCheckNum加1
	 */
	private boolean stateFlg = false;
	
	
	/**
	 *状态异常检查次数，由程管理器进行操作，
	 *		如果发现stateFlg为false，则stateCheckNum 加1 ，如果值大于120，则表示该线程已经出现问题，直接停止该线程，并重建
	 *		如果发现为true，则置0 ,
	 */
	private  int stateCheckNum = 0;
	private int stateCheckTopNum = 120;
	
	//定义错误次数，如果超过指定次数，则停止线程，
	private int errNum = 0;
	private int errTopNum = 100;//定义错误最大次数
	
	
	protected int sleepNum = 1000;//定义睡眠时间，默认为1000，单位为毫秒
	protected int sleepCount = 1;//定义睡眠指定次数后，执行一次代码，默认为一次
	
	protected String name = "";//定义线程标记名称
	
	protected String value1 = "";//基础数值1，用于保存从数据库中获取的数值
	protected String value2 = "";//基础数值2，用于保存从数据库中获取的数值
	
	
	/////////////////////////////////////////////////////////////////////////////////构造函数
	
	
	public BasicServiceThread(String name) {
		super();
		this.name = name;
		outInfo("创建一个线程，名称为：" + name );
	}
	
	/**
	 * 构造函数，定义睡眠时间,单位毫秒
	 * @param sleepNum
	 */
	public BasicServiceThread(String name, int sleepNum) {
		super();
		this.name = name;
		this.sleepNum = sleepNum;
		outInfo("创建一个线程，名称为：" + name + " ， 自定义睡眠时间为：" + sleepNum + " 毫秒 。");
	}
	
	
	/////////////////////////////////////////////////////////////////////////////////公共方法
	

	
	
	/**
	 * 是否允许执行循环，判断threadFlg的值进行返回
	 * @return
	 */
	protected boolean ifRun() {
		return threadFlg;
	}
	
	/**
	 * 停止运行，通过设置标记停止线程
	 */
	public void stopRun() {
		outInfo("开始停止线程  " + name  + " ............");
		threadFlg = false;
	}
	

	
	/**
	 * 校验状态，由线程管理器调用
	 * @return 
	 */
	public boolean checkState() {
		if(stateFlg) {
			//正常
			stateFlg = false;
			if(stateCheckNum > 10) {
				outInfo("线程状态发生异常次数：" + stateCheckNum  + "  ， 线程开始恢复正常..............");
			}
			stateCheckNum = 0;//初始化校验次数为0
//			outInfo("检查" + name + " 线程状态，状态正常");
			return true;
		}else {
			//不正常
			stateCheckNum ++ ;
			if( stateCheckNum > 5 && stateCheckNum < 10) {
				outInfo("检查" + name + " 线程状态，状态异常次数大于5次，次数：" + stateCheckNum);		
			}
			if(stateCheckNum > 110) {
				outInfo("检查" + name + " 线程状态，状态异常次数大于110次，次数：" + stateCheckNum);				
			}
			if(stateCheckNum >= stateCheckTopNum) {//达到或者超出3次，返回false
				outInfo("检查" + name + " 线程状态，状态异常，次数超过" + stateCheckTopNum + "次！" );
				return  false;
			}else {
				return true;//不超过三次，返回正确
			}
		}
	}
	
	
	public void run() {
		String msg = "";
		int num = 0;
		
		msg += threadServiceInit();//初始化服务
		
		if(msg.equals("")) {
			while (ifRun() && !isInterrupted()) {
				try {
					askCheckState();// 响应检查
					//start  执行代码
					num ++;
					if(num >= sleepCount) {
						num = 0;
						threadServiceRun();
					}
					
					// end 执行代码
					sleep();//睡眠
				}
				catch (InterruptedException ev) {
					// TODO: handle exception
					msg +="阻塞异常！" + ev.getMessage();
					threadLog.error(msg);
					break;
				}
				catch (Exception e) {
					// TODO: handle exception
					msg +=  " 运行失败：" + e.getMessage();
					threadLog.error(msg);
					e.printStackTrace();
					
				}
			}
			msg += "线程停止...........";			
		}
		
		if(!msg.equals("")) {
			outInfo(msg);
		}
	}
	
	//初始化服务
	protected String threadServiceInit() {
		outInfo("初始化服务代码！");
		return "";
	}
	
	//服务运行
	protected void threadServiceRun() {
		outInfo("开始进行服务代码！");
	}

	
	
	/////////////////////////////////////////////////////////////////////////////////私有方法
	
	
	@Override
	public String toString() {
		return "BasicServiceThread [threadLog=" + threadLog + ", threadFlg=" + threadFlg + ", stateFlg=" + stateFlg
				+ ", stateCheckNum=" + stateCheckNum + ", sleepNum=" + sleepNum + ", name=" + name + "]";
	}

	/**
	 * 睡眠指定的时间
	 * @throws InterruptedException
	 */
	protected void sleep() throws InterruptedException {
		sleep(sleepNum);
	}
	
	/**
	 * 线程本身响应状态检查
	 * @return
	 */
	protected void askCheckState() {
		if(!stateFlg) {
			stateFlg = true;
//			outInfo( name + "线程响应状态检查!");
		}
	}
	
	
	/**
	 * 输出信息
	 * @param msg
	 */
	protected void outInfo(String msg) {
//		System.out.println(msg);
		threadLog.info(name + "--->" +  msg);
	}
	
	/**
	 * 输出调试信息
	 * @param msg
	 * @param outDebugFlg
	 */
	protected void outInfo(String msg,boolean outDebugFlg){
		if(outDebugFlg && !msg.equals("")){
			threadLog.info(name + "--->" +  msg);
		}
	}
	
	/**
	 *输出错误信息 
	 */
	protected void outError(String msg) {
		threadLog.error(name + "--->" +  msg);
	}
	
	/**
	 * 输出错误信息
	 * @param msg
	 * @param outErrorFlg
	 */
	protected void outError(String msg,boolean outErrorFlg){
		if(outErrorFlg && !msg.equals("")){
			threadLog.error(name + "--->" +  msg);
		}
	}
	
	
	/**
	 * 校验错误，如果错误次数超过
	 */
	protected void checkError() {
		errNum ++ ;
		if(errNum >= errTopNum) {
			outError("发生错误次数超过最大允许次数 ,开始停止线程！");
			stopRun();
		}
	}
	
}
